package com.ice.base.util;

import com.arcsoft.face.FaceFeature;
import com.ice.base.ThreadPool.FaceToRoomDoubleRunAble;
import com.ice.base.ThreadPool.FaceToRoomRunAble;
import com.ice.base.constant.HCNetSDK;
import com.ice.base.model.SysLoginModel;
import com.ice.base.service.SysLoginService;
import com.ice.body.hardware.model.DeviceFace;
import com.ice.body.hardware.service.DeviceFaceService;
import com.ice.body.hardware.service.FaceToRoomService;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.logging.Level;

@Slf4j
@Component
public class FMSGCallBackUtil implements HCNetSDK.FMSGCallBack_V31{

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private FaceUtil faceUtil;
    @Autowired
    private SysLoginService sysLoginService;
    @Resource
    private FaceToRoomService faceToRoomService;
    @Autowired
    private FaceEngineTool faceEngineTool;
    @Resource
    private DeviceFaceService deviceFaceService;

    //各种布防预警方法
    public void AlarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) throws InterruptedException{
        String sAlarmType = "lCommand=" + lCommand;
        String[] newRow = new String[3];
        // 报警时间
        // 报警时间
        Date today = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String ipVal = new String(pAlarmer.sDeviceIP).trim();
        //报警设备IP地址
        String[] sIP  = new String(pAlarmer.sDeviceIP).split("\0", 2);
        // lCommand是传的报警类型
        switch (lCommand){
            //门禁主机报警
            case HCNetSDK.COMM_ALARM_ACS:
                HCNetSDK.NET_DVR_ACS_ALARM_INFO strACSInfo = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
                strACSInfo.write();
                Pointer pACSInfo = strACSInfo.getPointer();
                pACSInfo.write(0, pAlarmInfo.getByteArray(0, strACSInfo.size()), 0, strACSInfo.size());
                strACSInfo.read();
                sAlarmType = new String(strACSInfo.struAcsEventInfo.byCardNo).trim();
                String  userNo = String.valueOf(strACSInfo.struAcsEventInfo.dwEmployeeNo);
                if (StringUtils.isEmpty(userNo) || "0".equals(userNo) || StringUtils.isEmpty(ipVal)) {
                    return;
                }
                String dwYear= String.valueOf(strACSInfo.struTime.dwYear);
                String dwMonth= String.valueOf(strACSInfo.struTime.dwMonth);
                String dwDay= String.valueOf(strACSInfo.struTime.dwDay);
                String dwdwHourDay= String.valueOf(strACSInfo.struTime.dwHour);
                String dwMinute= String.valueOf(strACSInfo.struTime.dwMinute);
                String struTime=dwYear+"-"+dwMonth+"-"+dwDay+" "+dwdwHourDay+":"+dwMinute+":00";
                Date struTimes = null;
                try{
                    struTimes = dateFormat.parse(struTime);
                }catch (Exception e){
                    e.printStackTrace();
                   return;
                }
                long ltime= today.getTime()-struTimes.getTime();
                    log.info(ipVal +"设备刷脸！"+"监听到的工号：" + userNo);
                if (ltime>60000){
                    log.info(ipVal +"事件已超时"+ ltime/100+"秒不做处理");
                }else {
                    SysLoginModel user = sysLoginService.getByUserNo(userNo);
                    DeviceFace faceModel = deviceFaceService.getByIp(ipVal);
                    if (null == user ||null == faceModel) {
                        log.info("面部识别,系统非法用户或不存在设备绑定的userNo:" +userNo+",ip："+ipVal);
                        return;
                    }
                    //需要判断单人还是多人刷脸规则，欲从数据库设置
                    ThreadPoolExecutor threadPool = ThreadPoolUtil.getThreadPool();
                    //1单人刷脸，2双人刷脸
                    Integer faceType = faceModel.getFaceType();
                    //判定为 1开门 2出门
                    Integer deviceType = faceModel.getDeviceType();
                    //单人流程
                    if(1 == faceType){
                        System.out.println("房间："+faceModel.getWarehouseId() +",单人面部识别");
                        if (deviceType == 1) {
                            log.info("刷脸的设备IP地址====" + ipVal + ",单人进门刷脸的工号====" + userNo);
                            FaceToRoomRunAble runAble = new FaceToRoomRunAble(faceToRoomService,deviceType,user,faceModel);
                            threadPool.submit(runAble);
                        }
                  /*      if (deviceType == 2) {
                            log.info("刷脸的设备IP地址====" + ipVal + ",单人出门刷脸的工号====" + userNo);
                            FaceToRoomRunAble runAble = new FaceToRoomRunAble(faceToRoomService,deviceType,user,faceModel);
                            threadPool.submit(runAble);
                        }*/
                    //双人流程
                    }/*else if(2 ==faceType){
                        if (deviceType == 1) {
                            log.info("刷脸的设备IP地址====" + ipVal + ",双人进门刷脸的工号====" + userNo);
                            FaceToRoomDoubleRunAble runAble = new FaceToRoomDoubleRunAble(faceToRoomService,deviceType,user,faceModel);
                            threadPool.submit(runAble);
                        }
                        if (deviceType == 2) {
                            log.info("刷脸的设备IP地址====" + ipVal + ",双人出门刷脸的工号====" + userNo);
                            FaceToRoomDoubleRunAble runAble = new FaceToRoomDoubleRunAble(faceToRoomService,deviceType,user,faceModel);
                            threadPool.submit(runAble);
                        }
                    }*/

                    newRow[0] = dateFormat.format(today);
                    //报警类型
                    newRow[1] = sAlarmType;

                    newRow[2] = sIP[0];
                    String cardNoStr = new String(strACSInfo.struAcsEventInfo.byCardNo);
                    if(StringUtils.isNotEmpty(cardNoStr)){
                        if(deviceType == 1){// 如果是进门的人脸识别设备，则判断是否同步了照片，如果没有同步的话，就同步
                            cardNoStr = cardNoStr.trim();// 卡号去空格
                            if(sysLoginService.selectIsFaceByCardNo(cardNoStr) == 0){// 如果是第一次进行人脸录入
                                SysLoginModel faceUser = sysLoginService.getByUserNo(userNo);
                                faceUser.setCardNo(cardNoStr);
                                faceUser.setIsFace(1);
                                faceUser.setFacePath(BaseUtil.getVideoPath()+"faceImg\\"+cardNoStr+".jpg");
                                if(sysLoginService.modifyIsFaceByCardNo(faceUser)){// 更新人脸识别状态
                                    try {
                                        faceUtil.GetFaceCfg(faceUser,cardNoStr, faceModel);
                                    }catch (Exception e){
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                    }
                }

                break;
            case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT: //人脸识别结果上传
                long allstart = System.currentTimeMillis();
                //实时人脸抓拍上传
                HCNetSDK.NET_VCA_FACESNAP_RESULT strFaceSnapInfo = new HCNetSDK.NET_VCA_FACESNAP_RESULT();
                strFaceSnapInfo.write();
                Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();
                pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
                strFaceSnapInfo.read();
                sAlarmType = sAlarmType + "：人脸抓拍上传,人脸评分：" + strFaceSnapInfo.dwFaceScore + ",年龄段：" + strFaceSnapInfo.struFeature.byAgeGroup + "，性别：" + strFaceSnapInfo.struFeature.bySex;
                newRow[0] = dateFormat.format(today);
                //报警类型
                newRow[1] = sAlarmType;
                //报警设备IP地址
                sIP = new String(strFaceSnapInfo.struDevInfo.struDevIP.sIpV4).split("\0", 2);
                newRow[2] = sIP[0];

                String time = dateFormat.format(new Date()); // new Date()为获取当前系统时间

                String pathSmall="D:\\pic\\"+time+"small.jpg";
                String pathBig="D:\\pic\\"+time+"big.jpg";

                if (pAlarmer != null && pAlarmer.sDeviceIP != null) {
                    log.info("(人脸上传)设备IP地址=============" + ipVal);

                    //人脸图片写文件
                    try {
                        FileOutputStream small = new FileOutputStream(pathSmall);
                        FileOutputStream big = new FileOutputStream(pathBig);
                        if(strFaceSnapInfo.dwFacePicLen > 0)
                        {
                            try {
                                small.write(strFaceSnapInfo.pBuffer1.getByteArray(0, strFaceSnapInfo.dwFacePicLen), 0, strFaceSnapInfo.dwFacePicLen);
                                small.close();
                            } catch (IOException ex) {
                                java.util.logging.Logger.getLogger(FMSGCallBackUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                        if(strFaceSnapInfo.dwFacePicLen > 0)
                        {
                            try {
                                big.write(strFaceSnapInfo.pBuffer2.getByteArray(0, strFaceSnapInfo.dwBackgroundPicLen), 0, strFaceSnapInfo.dwBackgroundPicLen);
                                big.close();
                            } catch (IOException ex) {
                                java.util.logging.Logger.getLogger(FMSGCallBackUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    } catch (FileNotFoundException ex) {
                        java.util.logging.Logger.getLogger(FMSGCallBackUtil.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    //pathSmall 图片地址添加到readis中或保存起来
                    //对比人脸 -必要可以单独提出
                    FaceFeature currentFace= faceEngineTool.pathGetFace(pathSmall);
                    List< Map<String, Object>>  userMapList = (List< Map<String, Object>>)redisUtil.get("userList");
                    List< Map<String, Object>>  userFaceList = (List< Map<String, Object>>)redisUtil.get("userFaceList");
                    if(null == userFaceList){
                        userFaceList = new ArrayList<>();
                    }
                    for(Map<String,Object> user:userMapList){
                        FaceFeature faceFeature = (FaceFeature)redisUtil.hget("faceMap",user.get("userId").toString());
                        float score= faceEngineTool.CheckFace(currentFace, faceFeature);
                        System.out.println(""+score);
                        if(score>=0.75) {
                            Map<String,Object> map = new HashMap<String,Object>();
                            map.put("userId",user.get("userId").toString());
                            userFaceList.add(map);
                        }
                    }
                    redisUtil.set("userFaceList",userFaceList);
                    File fSmall = new File(pathSmall);
                    File fBig = new File(pathSmall);
                    if(fSmall.exists()){
                        fSmall.delete();
                    }
                    if(fBig.exists()){
                        fBig.delete();
                    }
                }
                long allend = System.currentTimeMillis();
                //System.out.println("总用时:"+(allend-allstart)+"ms");
                break;
            case HCNetSDK.COMM_ID_INFO_ALARM: // 身份证信息
                HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM strIDCardInfo = new HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM();
                strIDCardInfo.write();
                Pointer pIDCardInfo = strIDCardInfo.getPointer();
                pIDCardInfo.write(0, pAlarmInfo.getByteArray(0, strIDCardInfo.size()), 0, strIDCardInfo.size());
                strIDCardInfo.read();

                sAlarmType = sAlarmType + "：门禁身份证刷卡信息，身份证号码："+  new String(strIDCardInfo.struIDCardCfg.byIDNum).trim() + "，姓名：" +
                        new String(strIDCardInfo.struIDCardCfg.byName).trim() + "，报警主类型：" + strIDCardInfo.dwMajor + "，报警次类型：" + strIDCardInfo.dwMinor;

                newRow[0] = dateFormat.format(today);
                //报警类型
                newRow[1] = sAlarmType;
                newRow[2] = sIP[0];
                break;
            default:
                newRow[0] = dateFormat.format(today);
                //报警类型
                newRow[1] = sAlarmType;
                newRow[2] = sIP[0];
                //alarmTableModel.insertRow(0, newRow);
                break;
        }
    }

    @Override
    public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) throws InterruptedException {
        AlarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
        return true;
    }
}